#pragma once

#include"InetAddr.hpp"
#include"Logger.hpp"
#include"Util.hpp"
#include<iostream>
#include<sys/epoll.h>

class Epoller
{
private:
    int EpollerHelper(int sockfd , uint32_t events , int oper)
    {
        epoll_event ev;
        ev.data.fd = sockfd;
        ev.events = events;
        //使用epoll_ctl
        return epoll_ctl(_epfd , oper, sockfd , &ev);
    }
public:
    Epoller()
    {
        //在构造的时候创建epoll模型
        _epfd = epoll_create(128);//参数代表底层红黑树的节点个数，现在没有什么用了
        if(_epfd < 0)
        {
            LOG(LogLevel::FATAL) << "创建epoll模型失败";
            exit(1);
        }
        LOG(LogLevel::INFO) << "创建epoll 模型成功";
    }
    ~Epoller(){}

    //提供可以向反应堆添加、修改、删除的接口
    void AddEvent(int sockfd , uint32_t events)//关心哪一个fd 的哪一个事件
    {
        // epoll_event ev;
        // ev.data.fd = sockfd;
        // ev.events = events;
        // //使用epoll_ctl
        // int n = epoll_ctl(_epfd , EPOLL_CTL_ADD, sockfd , &ev);
        int n  = EpollerHelper(sockfd , events , EPOLL_CTL_ADD);
        if( n < 0)
        {
            //添加失败
            LOG(LogLevel::WARNING) << "添加sockf:" << sockfd << "失败, events : " << Events2String(events);
        }
        LOG(LogLevel::INFO) << "添加sockf:" << sockfd << "失败, events : " << Events2String(events);

    }
    void ModEvent(int sockfd , uint32_t events)
    {
        // epoll_events ev;
        // ev.data.fd = sockfd;
        // ev.events = events;
        // int n = epoll_ctl(_epfd , EPOLL_CTL_MOD , sockfd, &ev);
        int n  = EpollerHelper(sockfd , events , EPOLL_CTL_MOD);
        if( n < 0)
        {
            //添加失败
            LOG(LogLevel::WARNING) << "修改sockf:" << sockfd << "失败, events : " << Events2String(events);
        }
        LOG(LogLevel::INFO) << "修改sockf:" << sockfd << "失败, events : " << Events2String(events);
    }
    void DelEvent(int sockfd)
    {
        int n = epoll_ctl(_epfd , EPOLL_CTL_DEL , sockfd, nullptr);
        if( n < 0)
        {
            //添加失败
            LOG(LogLevel::WARNING) << "删除sockf:" << sockfd << "失败";
        }
        LOG(LogLevel::INFO) << "删除sockf:" << sockfd << "失败";
    }

    int Wait(struct epoll_event * revs ,int num , int timeout )
    {
        int n = epoll_wait(_epfd ,revs, num , timeout);
        if( n == 0)
        {
            LOG(LogLevel::INFO) << "无事件就绪";
        }
        else if( n < 0)
        {
            LOG(LogLevel::WARNING) << "epoll_wait 出错";
        }
        else{
            LOG(LogLevel::INFO) << n << "个事件就绪";
        }
        return n;
    }
private:
    int _epfd;
};  